#include"../include/lib_headers.h"

char* add_file(char *pt, char *dt, char *data_file_path) {

	int i = 0, j = 0, k = 0, match = 0, t = 0, y = 1, counter = 0;
	char parent[SIZE] = "", directory[SIZE] = "", file_text[(BLOCKSIZE)] = "", *s,
			input[SIZE] = "", *split_char, *p[SIZE], copy[SIZE] = "", file_ext[SIZE] = "";
	node *temp, *prev;

	
	/* File will not be created if VFS is not mounted */
	if (h == 0 || l1 == 0) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_07);
		return output_message;
	}
	
	/* Checking Insufficient arguments */
	if(strlen(pt) == 0 || strlen(dt) == 0 || strlen(data_file_path) == 0){
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_00);
		return output_message;
	}
	
	/* Validating the name */	
	if(validate_name(dt) == FAILURE){
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_02);
		return output_message;
	}

	/* Copying the Destiantion Directory Path to Retrieve the extension */
	/* To store dt somewhere so that later it can be used for extracting file_extension */
	strcpy(file_ext, dt);

	/* File does not exist from where to be copied */
	FILE *fp = fopen(data_file_path, "rb");
	if (fp == NULL) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_00);
		return output_message;
	}
	
	fseek(fp, 0, SEEK_END);

	/* File Size is too large */
	if(ftell(fp) > (BLOCKSIZE) ){
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_06);
		return output_message;
	}
	
	rewind(fp);

	/* Check if File Extension has been provided */
	if (check_character(dt,'.') == FAILURE || check_character(data_file_path,'.') == FAILURE ) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_00);
		return output_message;
	}
	
	/* File extension should be the same */
/*	if(strcmp(file_extension(dt), file_extension(data_file_path)) != 0){
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_00);
		return output_message;
	}
*/
	if(file_extension(dt) == "txt" && (file_extension(data_file_path) != "h" || file_extension(data_file_path) != "txt" ) ){
		sprintf(output_message,"%s %s","updatefile_FAILURE",ERR_VFS_UPDATEFILE_02);	
		return output_message;		
	}
	/*Check to see if all the FDs have been exhausted */
	if (h->usedFds == h->maxFds) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_04);
		return output_message;
	}

	/* Concatenating the Directory name with the Filepath */
	pt = add_slash(pt);
	dt = add_slash(dt);
	strcpy(parent, pt);
	strcpy(directory, dt);
	strcat(parent, directory);

	/* File already exists */
	if (find_node(l1->next, parent) != NULL) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_03);
		return output_message;
	}

	/*Destination Directory Does not Exist */
	if (strcmp(pt, "/") != 0 && find_node(l1->next, pt) == NULL || pt[0] != '/' ) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_00);
		return output_message;
	}

	/* Destination Directory Path is path of a file */
	if (strcmp(pt, "/") != 0
			&& strcmp(find_node(l1->next, pt)->fd_pointer->fileType, "dir")
					!= 0) {
		sprintf(output_message, "%s %s", "addfile_FAILURE", ERR_VFS_ADDFILE_00);
		return output_message;
	}

	/* Code to split the Directory into strings */
	split_char = "/";
	i = splits_directory(parent, p, split_char);

	/* code to insert if no directory exists */
	if (l1->next == NULL) {
		j = 0;
		/*Check to see if all the FDs have been exhausted */
		if (h->usedFds == h->maxFds) {
			sprintf(output_message, "%s %s", "addfile_FAILURE",
					ERR_VFS_ADDFILE_04);
			return output_message;
		}
		node *n = (node*) malloc(sizeof(node));
		fd *f = (fd*) malloc(sizeof(fd));
		n->fd_pointer = f;
		strcpy(f->fileName, p[j]);
		strcpy(f->fullPath, "/");
		strcat(f->fullPath, p[j]);
		/* strcat(f->fullPath, "/"); */
		strcpy(copy, p[j]);
		strcat(copy, "/");
		l1->next = n;
		n->child = NULL;
		n->sibling = NULL;
		f->blockno = freelist_alloc(); //now
		freelist[f->blockno] = 1; //now
		h->usedFds++;
		if(write_into_file(f->blockno, data_file_path)!=1)
		{
			sprintf(output_message, "%s %s", "addfile_FAILURE",ERR_VFS_ADDFILE_05);
			return output_message;
		}
		f->fileSize = length_of_file(fp);
		strcpy(f->fileType, file_extension(file_ext));
		j++;
		insert(f);
		htable_insert(hashtable, *f); // insert into hash table

		temp = n;
		while (j < i) {
			/*Check to see if all the FDs have been exhausted */
			if (h->usedFds == h->maxFds) {
				sprintf(output_message, "%s %s", "addfile_FAILURE",
						ERR_VFS_ADDFILE_04);
				return output_message;
			}

			node *n = (node*) malloc(sizeof(node));
			fd *f = (fd*) malloc(sizeof(fd));
			n->fd_pointer = f;
			strcat(copy, "/");
			strcat(copy, p[j]);
			/* strcat(copy, "/"); */
			strcpy(f->fileName, p[j]);
			strcpy(f->fullPath, copy);
			temp->child = n;
			n->child = NULL;
			n->sibling = NULL;
			f->blockno = freelist_alloc();
			freelist[f->blockno] = 1;
			h->usedFds++;
			if(write_into_file(f->blockno, data_file_path)!=1)
			{
				sprintf(output_message, "%s %s", "addfile_FAILURE",ERR_VFS_ADDFILE_05);
				return output_message;
			}
			f->fileSize = length_of_file(fp);			
			strcpy(f->fileType, file_extension(file_ext));
			temp = n;
			j++;

			/* insert into hash table */
			insert(f);
			htable_insert(hashtable, *f);
		}
		sprintf(output_message, "%s", "addfile_SUCCESS");
		return output_message;
	}

	/* Code to insert a directory if already a directory exists */
	temp = l1->next;
	strcpy(copy, "");
	split_char = "/";
	i = splits_directory(parent, p, split_char);
	match = 0;

	if (l1->next != NULL) {
		j = 0;
		t = 0;
		temp = l1->next;
		while (j < i) {
			while (temp != NULL) {
				if (strcmp(temp->fd_pointer->fileName, p[j]) == 0) {
					match = 1;
					strcat(copy, "/");
					strcat(copy, p[j]);
					/* strcat(copy, "/"); */
					j++;
					prev = temp;
					temp = temp->child;
					if (temp == NULL) {
						t = 1;
					}
					if (j == i)
						break;
				}
				if (match == 0) {
					prev = temp;
					temp = temp->sibling;
				} else if (match == 1) {
					match = 0;
					continue;
				}
			}
			if (temp == NULL) {
				strcat(copy, "/");
				strcat(copy, p[j]);
				/* strcat(copy, "/"); */
				if (h->usedFds == h->maxFds) {
					sprintf(output_message, "%s %s", "addfile_FAILURE",
							ERR_VFS_ADDFILE_04);
					return output_message;
				}
				node *n = (node*) malloc(sizeof(node));
				fd *f = (fd*) malloc(sizeof(fd));
				n->fd_pointer = f;
				n->child = NULL;
				n->sibling = NULL;
				f->blockno = freelist_alloc();
				freelist[f->blockno] = 1;
				h->usedFds++;
				if(write_into_file(f->blockno, data_file_path)!=1)
				{
					sprintf(output_message, "%s %s", "addfile_FAILURE",ERR_VFS_ADDFILE_05);
					return output_message;
				}
				f->fileSize = length_of_file(fp);				
				strcpy(f->fileType, file_extension(file_ext));
				strcpy(f->fileName, p[j]);
				strcpy(f->fullPath, copy);

				/* Insert into hash table */
				insert(f);
				htable_insert(hashtable, *f);

				/* If terminates because of no child and Else is Reached end of linked */
				if (t == 1) {
					prev->child = n;
				} else if (t == 0) {
					prev->sibling = n;
					t = 1;
				}
				j++;
				temp = n;
			}
		}
		sprintf(output_message, "%s", "addfile_SUCCESS");
		return output_message;
	}
}

